package vip.xiaonuo.wydemop;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.Cookie;
import com.microsoft.playwright.options.WaitForSelectorState;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * Playwright Java 演示示例
 * 演示如何使用本地 Chromium 浏览器访问抖音创作者平台
 */
@Component
public class PlaywrightDemo {

    private static final String USER_DATA_DIR = "playwright-user-data";
    private static final String QR_CODE_IMAGE_PATH = "qr-code.png";

    /**
     * 获取本地 Chromium 浏览器路径
     */
    private String getLocalChromiumPath() {
        try {
            // 从 resources/chromium 目录获取浏览器路径
            ClassPathResource resource = new ClassPathResource("chromium/chromium-win64/chrome-win/chrome.exe");
            if (resource.exists()) {
                return resource.getFile().getAbsolutePath();
            }
            
            // 备用路径：项目根目录下的 chromium
            Path fallbackPath = Paths.get("src/main/resources/chromium/chromium-win64/chrome-win/chrome.exe");
            if (fallbackPath.toFile().exists()) {
                return fallbackPath.toAbsolutePath().toString();
            }
            
            System.out.println("本地 Chromium 未找到，将使用自动下载的浏览器");
            return null;
            
        } catch (Exception e) {
            System.out.println("获取本地浏览器路径失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 基础示例：使用本地浏览器打开抖音创作者平台
     */
    public void basicExample() {
        try (Playwright playwright = Playwright.create()) {
            
            String chromiumPath = getLocalChromiumPath();
            Browser browser;
            
            if (chromiumPath != null) {
                System.out.println("使用本地 Chromium: " + chromiumPath);
                // 使用本地浏览器
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setExecutablePath(Paths.get(chromiumPath))
                        .setHeadless(false)
                        .setSlowMo(1000));
            } else {
                System.out.println("使用默认 Chromium（需要网络下载）");
                // 使用默认浏览器（会自动下载）
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setHeadless(false)
                        .setSlowMo(1000));
            }

            // 创建新页面
            Page page = browser.newPage();

            System.out.println("正在打开抖音创作者平台...");
            
            // 访问抖音创作者平台
            page.navigate("https://creator.douyin.com/");

            // 等待页面加载完成
            page.waitForLoadState();

            // 设置页面标题
            System.out.println("页面标题: " + page.title());

            // 等待 5 秒让用户观察页面
            page.waitForTimeout(5000);

            // 关闭浏览器
            browser.close();
            System.out.println("浏览器已关闭");
            
        } catch (Exception e) {
            System.err.println("执行过程中出现错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 进阶示例：与页面元素交互
     */
    public void advancedExample() {
        try (Playwright playwright = Playwright.create()) {
            
            String chromiumPath = getLocalChromiumPath();
            Browser browser;
            
            if (chromiumPath != null) {
                System.out.println("使用本地 Chromium: " + chromiumPath);
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setExecutablePath(Paths.get(chromiumPath))
                        .setHeadless(false)
                        .setSlowMo(2000));
            } else {
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setHeadless(false)
                        .setSlowMo(2000));
            }

            Page page = browser.newPage();

            // 设置视口大小
            page.setViewportSize(1920, 1080);

            System.out.println("正在访问抖音创作者平台...");
            page.navigate("https://creator.douyin.com/");

            // 等待页面加载
            page.waitForLoadState();
            System.out.println("页面标题: " + page.title());

            // 尝试查找登录按钮
            try {
                page.waitForSelector("text=登录", new Page.WaitForSelectorOptions()
                        .setTimeout(10000)
                        .setState(WaitForSelectorState.VISIBLE));
                
                System.out.println("找到登录按钮");
                
            } catch (Exception e) {
                System.out.println("未找到登录按钮，可能页面结构已变化或已登录状态");
            }

            // 截屏保存
            page.screenshot(new Page.ScreenshotOptions()
                    .setPath(java.nio.file.Paths.get("douyin-creator.png")));
            System.out.println("已保存截图: douyin-creator.png");

            // 等待用户观察
            page.waitForTimeout(10000);

            browser.close();
            System.out.println("演示完成");

        } catch (Exception e) {
            System.err.println("执行过程中出现错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 手机模拟示例：模拟手机访问
     */
    public void mobileExample() {
        try (Playwright playwright = Playwright.create()) {
            
            String chromiumPath = getLocalChromiumPath();
            Browser browser;
            
            if (chromiumPath != null) {
                System.out.println("使用本地 Chromium (手机模式): " + chromiumPath);
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setExecutablePath(Paths.get(chromiumPath))
                        .setHeadless(false)
                        .setSlowMo(1500));
            } else {
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setHeadless(false)
                        .setSlowMo(1500));
            }

            // 创建手机设备上下文
            var context = browser.newContext(new Browser.NewContextOptions()
                    .setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15")
                    .setViewportSize(375, 812)
                    .setDeviceScaleFactor(2)
                    .setIsMobile(true)
                    .setHasTouch(true));

            Page page = context.newPage();

            System.out.println("正在使用手机模式访问抖音创作者平台...");
            page.navigate("https://creator.douyin.com/");

            page.waitForLoadState();
            System.out.println("手机模式页面标题: " + page.title());

            // 截屏
            page.screenshot(new Page.ScreenshotOptions()
                    .setPath(java.nio.file.Paths.get("douyin-creator-mobile.png")));
            System.out.println("已保存手机版截图: douyin-creator-mobile.png");

            page.waitForTimeout(8000);

            browser.close();
            System.out.println("手机模式演示完成");

        } catch (Exception e) {
            System.err.println("手机模式执行错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 二维码登录示例：获取二维码并在控制台展示，等待用户扫描登录
     */
    public void qrLoginExample() {
        try (Playwright playwright = Playwright.create()) {
            
            String chromiumPath = getLocalChromiumPath();
            Browser browser;
            
            if (chromiumPath != null) {
                System.out.println("使用本地 Chromium 进行二维码登录: " + chromiumPath);
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setExecutablePath(Paths.get(chromiumPath))
                        .setHeadless(false)
                        .setSlowMo(1000));
            } else {
                System.out.println("使用默认 Chromium 进行二维码登录");
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setHeadless(false)
                        .setSlowMo(1000));
            }

            // 创建浏览器上下文，尝试加载已保存的状态
            BrowserContext context;
            Path stateFile = Paths.get(USER_DATA_DIR, "state.json");
            if (Files.exists(stateFile)) {
                try {
                    context = browser.newContext(new Browser.NewContextOptions()
                            .setStorageStatePath(stateFile));
                    System.out.println("加载已保存的登录状态: " + stateFile);
                } catch (Exception e) {
                    System.err.println("加载登录状态失败: " + e.getMessage());
                    context = browser.newContext();
                    System.out.println("使用新的浏览器会话");
                }
            } else {
                context = browser.newContext();
                System.out.println("未找到保存的状态文件，使用新的浏览器会话");
            }
            
            Page page = context.newPage();
            page.setViewportSize(1920, 1080);

            System.out.println("正在访问抖音创作者平台...");
            page.navigate("https://creator.douyin.com/");
            page.waitForLoadState();

            // 检查是否已经登录
            try {
                // 等待一下让页面完全加载
                page.waitForTimeout(3000);
                
                // 检查是否存在登录按钮或二维码
                if (page.locator("text=登录").count() > 0 || page.locator("canvas").count() > 0 || 
                    page.locator("img[alt*='二维码']").count() > 0 || page.locator("img[src*='qr']").count() > 0 ||
                    page.locator(".qrcode_img-NPVTJs").count() > 0 || page.locator("img[src^='data:image/png;base64']").count() > 0 ||
                    page.locator(".qrcode-vz0gH7").count() > 0) {
                    
                    System.out.println("检测到登录页面，正在寻找二维码...");
                    
                    // 尝试多种方式查找二维码
                    com.microsoft.playwright.Locator qrLocator = null;
                    
                    // 方式1：查找抖音特定的二维码img（基于你提供的HTML结构）
                    if (page.locator(".qrcode_img-NPVTJs").count() > 0) {
                        qrLocator = page.locator(".qrcode_img-NPVTJs").first();
                        System.out.println("找到抖音特定的二维码img元素");
                    }
                    // 方式2：查找包含data:image/png;base64的img
                    else if (page.locator("img[src^='data:image/png;base64']").count() > 0) {
                        qrLocator = page.locator("img[src^='data:image/png;base64']").first();
                        System.out.println("找到base64编码的二维码图片");
                    }
                    // 方式3：查找二维码容器内的img
                    else if (page.locator(".qrcode-vz0gH7 img").count() > 0) {
                        qrLocator = page.locator(".qrcode-vz0gH7 img").first();
                        System.out.println("找到二维码容器内的img元素");
                    }
                    // 方式4：通用查找包含qrcode类名的img
                    else if (page.locator("img[class*='qrcode']").count() > 0) {
                        qrLocator = page.locator("img[class*='qrcode']").first();
                        System.out.println("找到包含qrcode类名的img元素");
                    }
                    // 方式5：查找img元素包含二维码关键词
                    else if (page.locator("img[alt*='二维码']").count() > 0) {
                        qrLocator = page.locator("img[alt*='二维码']").first();
                        System.out.println("找到img二维码元素(alt)");
                    }
                    // 方式6：查找canvas元素（可能包含二维码）
                    else if (page.locator("canvas").count() > 0) {
                        qrLocator = page.locator("canvas").first();
                        System.out.println("找到canvas二维码元素");
                    }
                    // 方式7：查找src包含qr的img元素
                    else if (page.locator("img[src*='qr']").count() > 0) {
                        qrLocator = page.locator("img[src*='qr']").first();
                        System.out.println("找到img二维码元素(src)");
                    }
                    // 方式8：通用二维码容器查找
                    else {
                        // 尝试查找常见的二维码容器类名
                        String[] qrSelectors = {
                            ".qr-code", ".qrcode", ".qr_code", ".login-qr", 
                            "[class*='qr']", "[id*='qr']", ".scan-code"
                        };
                        
                        for (String selector : qrSelectors) {
                            if (page.locator(selector).count() > 0) {
                                qrLocator = page.locator(selector).first();
                                System.out.println("找到二维码容器: " + selector);
                                break;
                            }
                        }
                    }

                    if (qrLocator != null) {
                        // 尝试从img标签的src获取base64图片
                        boolean savedFromBase64 = false;
                        try {
                            String tagName = qrLocator.evaluate("el => el.tagName").toString().toLowerCase();
                            if ("img".equals(tagName)) {
                                String src = qrLocator.getAttribute("src");
                                if (src != null && src.startsWith("data:image/png;base64,")) {
                                    // 提取base64数据并保存
                                    String base64Data = src.substring("data:image/png;base64,".length());
                                    byte[] imageBytes = java.util.Base64.getDecoder().decode(base64Data);
                                    Files.write(Paths.get(QR_CODE_IMAGE_PATH), imageBytes);
                                    System.out.println("从base64数据保存二维码: " + QR_CODE_IMAGE_PATH);
                                    savedFromBase64 = true;
                                }
                            }
                        } catch (Exception e) {
                            System.out.println("base64提取失败，使用截图方式: " + e.getMessage());
                        }
                        
                        // 如果base64提取失败，则使用截图方式
                        if (!savedFromBase64) {
                            qrLocator.screenshot(new com.microsoft.playwright.Locator.ScreenshotOptions()
                                    .setPath(Paths.get(QR_CODE_IMAGE_PATH)));
                            System.out.println("通过截图保存二维码: " + QR_CODE_IMAGE_PATH);
                        }
                        
                        System.out.println("\n===========================================");
                        System.out.println("二维码获取成功！");
                        System.out.println("===========================================");
                        
                        // 在控制台显示二维码
                        displayQRCodeInConsole(QR_CODE_IMAGE_PATH);
                        
                        System.out.println("===========================================");
                        System.out.println("📱 请使用抖音APP扫描上方二维码进行登录");
                        System.out.println("💡 如果控制台显示不清楚，请打开文件: " + QR_CODE_IMAGE_PATH);  
                        System.out.println("===========================================\n");
                        
                        // 等待登录完成（检测页面变化或URL变化）
                        System.out.println("等待登录完成...");
                        
                        // 设置较长的超时时间等待用户扫码登录
                        long startTime = System.currentTimeMillis();
                        long timeout = 300000; // 5分钟超时
                        boolean loginSuccess = false;
                        
                        while (System.currentTimeMillis() - startTime < timeout) {
                            try {
                                // 检查是否登录成功（页面上不再有登录按钮）
                                if (page.locator("text=登录").count() == 0 && 
                                    page.locator("canvas").count() == 0) {
                                    loginSuccess = true;
                                    break;
                                }
                                page.waitForTimeout(2000); // 每2秒检查一次
                            } catch (Exception e) {
                                // 继续等待
                            }
                        }
                        
                        if (loginSuccess) {
                            System.out.println("登录成功！正在保存登录状态...");
                            
                            // 保存浏览器状态（包括cookies、localStorage等）
                            try {
                                // 确保目录存在
                                Files.createDirectories(Paths.get(USER_DATA_DIR));
                                context.storageState(new BrowserContext.StorageStateOptions()
                                        .setPath(Paths.get(USER_DATA_DIR, "state.json")));
                                System.out.println("登录状态已保存到: " + USER_DATA_DIR + "/state.json");
                            } catch (Exception e) {
                                System.err.println("保存登录状态失败: " + e.getMessage());
                            }
                            
                            // 截取登录后的页面
                            page.screenshot(new Page.ScreenshotOptions()
                                    .setPath(Paths.get("douyin-logged-in.png")));
                            System.out.println("登录后截图已保存: douyin-logged-in.png");
                            
                            page.waitForTimeout(5000); // 让用户看到登录后的页面
                        } else {
                            System.out.println("登录超时，请重试");
                        }
                        
                    } else {
                        System.out.println("未找到二维码元素，请检查页面结构");
                        // 保存页面截图用于调试
                        page.screenshot(new Page.ScreenshotOptions()
                                .setPath(Paths.get("login-page-debug.png")));
                        System.out.println("页面截图已保存用于调试: login-page-debug.png");
                    }
                    
                } else {
                    System.out.println("用户可能已经登录，或者页面结构已变化");
                    // 保存当前页面截图
                    page.screenshot(new Page.ScreenshotOptions()
                            .setPath(Paths.get("current-page.png")));
                    System.out.println("当前页面截图: current-page.png");
                }
                
            } catch (Exception e) {
                System.err.println("二维码登录过程中出现错误: " + e.getMessage());
                e.printStackTrace();
            }

            browser.close();
            System.out.println("二维码登录流程结束");
            
        } catch (Exception e) {
            System.err.println("二维码登录失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 检查登录状态
     */
    public boolean checkLoginStatus() {
        try (Playwright playwright = Playwright.create()) {
            
            String chromiumPath = getLocalChromiumPath();
            Browser browser;
            
            if (chromiumPath != null) {
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setExecutablePath(Paths.get(chromiumPath))
                        .setHeadless(true)); // 使用headless模式快速检查
            } else {
                browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                        .setHeadless(true));
            }

            // 创建浏览器上下文，尝试加载已保存的状态
            BrowserContext context;
            Path stateFile = Paths.get(USER_DATA_DIR, "state.json");
            if (Files.exists(stateFile)) {
                try {
                    context = browser.newContext(new Browser.NewContextOptions()
                            .setStorageStatePath(stateFile));
                    System.out.println("加载已保存的登录状态: " + stateFile);
                } catch (Exception e) {
                    System.err.println("加载登录状态失败: " + e.getMessage());
                    context = browser.newContext();
                    System.out.println("使用新的浏览器会话");
                }
            } else {
                context = browser.newContext();
                System.out.println("未找到保存的状态文件，使用新的浏览器会话");
            }
            
            Page page = context.newPage();
            page.navigate("https://creator.douyin.com/");
            page.waitForLoadState();
            page.waitForTimeout(3000);

            // 检查是否存在登录按钮
            boolean hasLoginButton = page.locator("text=登录").count() > 0;
            boolean hasQRCode = page.locator("canvas").count() > 0 || 
                               page.locator("img[alt*='二维码']").count() > 0;
            
            browser.close();
            
            // 如果没有登录按钮和二维码，说明已经登录
            boolean isLoggedIn = !hasLoginButton && !hasQRCode;
            System.out.println("登录状态检查结果: " + (isLoggedIn ? "已登录" : "未登录"));
            
            return isLoggedIn;
            
        } catch (Exception e) {
            System.err.println("检查登录状态失败: " + e.getMessage());
            return false;
        }
    }


    /**
     * 在控制台显示二维码
     */
    private void displayQRCodeInConsole(String imagePath) {
        try {
            BufferedImage image = ImageIO.read(new File(imagePath));
            
            // 先尝试解码二维码内容
            String qrContent = null;
            try {
                BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(
                        new BufferedImageLuminanceSource(image)));
                Result result = new MultiFormatReader().decode(binaryBitmap);
                qrContent = result.getText();
                System.out.println("✅ 二维码解码成功!");
                System.out.println("🔗 内容: " + qrContent);
            } catch (Exception e) {
                System.out.println("⚠️  二维码解码失败，但图像已保存供扫描");
            }
            
            // 获取图像尺寸
            int width = image.getWidth();
            int height = image.getHeight();
            System.out.println("📐 图像尺寸: " + width + "x" + height + "px");
            
            // 尝试显示ASCII二维码（紧凑模式）
            try {
                displayCompactQRCode(image, width, height);
            } catch (Exception e) {
                System.err.println("ASCII显示失败: " + e.getMessage());
                // 提供备用方案
                displaySimpleQRInfo(imagePath, qrContent);
            }
            
        } catch (IOException e) {
            System.err.println("❌ 读取二维码图像失败: " + e.getMessage());
            System.out.println("📁 请手动打开文件: " + imagePath);
        }
    }
    
    /**
     * 显示紧凑的ASCII二维码
     */
    private void displayCompactQRCode(BufferedImage image, int width, int height) {
        // 紧凑尺寸：15-20字符宽度
        int targetSize = Math.min(20, Math.max(15, Math.min(width, height) / 15));
        
        System.out.println("\n📱 二维码 (紧凑显示):");
        System.out.println("┌" + "─".repeat(targetSize) + "┐");
        
        for (int y = 0; y < targetSize; y++) {
            StringBuilder line = new StringBuilder("│");
            for (int x = 0; x < targetSize; x++) {
                // 采样原图像的对应位置
                int sampleX = (x * width) / targetSize;
                int sampleY = (y * height) / targetSize;
                
                // 边界检查
                sampleX = Math.min(sampleX, width - 1);
                sampleY = Math.min(sampleY, height - 1);
                
                // 获取像素灰度值
                int rgb = image.getRGB(sampleX, sampleY);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                int gray = (r + g + b) / 3;
                
                // 使用单个字符，更紧凑
                if (gray < 128) {
                    line.append("█"); // 黑色方块
                } else {
                    line.append("·"); // 小点表示白色区域，比空格更清晰
                }
            }
            line.append("│");
            System.out.println(line.toString());
        }
        
        System.out.println("└" + "─".repeat(targetSize) + "┘");
        System.out.println("💡 太小看不清？请直接扫描图片文件: " + QR_CODE_IMAGE_PATH);
    }
    
    /**
     * 显示简化的二维码信息
     */
    private void displaySimpleQRInfo(String imagePath, String qrContent) {
        System.out.println("\n" + "=".repeat(60));
        System.out.println("            二维码信息");
        System.out.println("=".repeat(60));
        System.out.println("📁 图片文件: " + imagePath);
        if (qrContent != null) {
            System.out.println("🔗 扫描内容: " + qrContent);
        }
        System.out.println("📱 请使用手机抖音APP直接扫描保存的图片文件");
        System.out.println("💡 或者在浏览器中打开图片进行扫描");
        System.out.println("=".repeat(60) + "\n");
    }
}